#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "consoleeditor.h"
#include "editor.h"
#include <QProcess>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //整体
    QSplitter* main = new QSplitter(this);

    //左侧文件列表
    QTreeView* fileList = new QTreeView(this);
    _model = new QStandardItemModel(this);
    //修改文件名时会触发
    connect(_model, &QStandardItemModel::itemChanged, this, &MainWindow::onFileListItemChanged);

    //设置宽度
    fileList->setMinimumWidth(200);
    fileList->setMaximumWidth(300);
    fileList->setModel(_model);
    //设置槽函数
    connect(fileList, &QTreeView::clicked, this, &MainWindow::onFileListItemClicked);

    //右侧布局
    QSplitter* right = new QSplitter(main);
    //设置右侧布局为垂直布局
    right->setOrientation(Qt::Orientation::Vertical);

    //右侧的编辑器和控制台
    _tab = new QTabWidget(this);
    _tab->setTabsClosable(true);
    //设置槽函数 能关闭编辑器
    connect(_tab, &QTabWidget::tabCloseRequested, this, &MainWindow::onTabWidgetClosed);

    _console = new QTabWidget(this);
    _console->setTabsClosable(true);
    connect(_console, &QTabWidget::tabCloseRequested, [this](int index) {
        QWidget* widget = _console->widget(index);
        if (widget != nullptr) {
            ConsoleEditor* editor = static_cast<ConsoleEditor*>(widget);
            _console->removeTab(index);
            delete editor;
        }
    });

    //将tab和console添加到right侧布局
    right->addWidget(_tab);
    right->addWidget(_console);
    //文件列表和右侧布局添加到main
    main->addWidget(fileList);
    main->addWidget(right);

    ui->verticalLayout->addWidget(main);
    setCentralWidget(ui->verticalLayoutWidget);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_open_project_triggered()
{
    QString fileName = QFileDialog::getExistingDirectory(this, tr("打开程序项目"), "D:\\editor", QFileDialog::ShowDirsOnly);
    if (fileName.isEmpty()) {
        return;
    }
    _project = fileName;
    QStringList header;
    header << _project;
    _model->setHorizontalHeaderLabels(header);
    getSubdirAndFiles(_project, _project, nullptr);
}

void MainWindow::onFileListItemClicked(const QModelIndex &index)
{   
    QStandardItem* item = _model->itemFromIndex(index);
    QString itemText = item->text();
    QStandardItem* parent = item->parent();
    QString fileName = "";
    QFileInfo fileinfo(itemText);
    if (fileinfo.isDir()) {
        return;
    }
    if (parent) {
        fileName = parent->text() + "/" + itemText;
    } else {
        fileName = _project + "/" + itemText;
    }

    //判断当前文件是否被打开过 如果打开过就不需要重复打开
    for (int i = 0; i < _tab->count(); ++i) {
        Editor* widget = (Editor*)_tab->widget(i);
        if (widget->getFileName() == fileName) {
            _tab->setCurrentIndex(i);
            return;
        }
    }

    QFile file(fileName);
    fileinfo.setFile(fileName);
    if (fileinfo.isDir()) {
        return;
    }
    if (!file.exists()) {
        QMessageBox::warning(this,tr("错误"), tr("文件不存在"), QMessageBox::Ok);
    }
    if (!file.open(QIODeviceBase::ReadOnly|QIODeviceBase::Text)) {
        QMessageBox::warning(this, tr("错误"), tr("文件打开失败"), QMessageBox::Ok);
    }
    //读取文件内容并设置到编辑器中
    Editor* editor = new Editor();
    editor->setPlainText(QString::fromUtf8(file.readAll()));
    editor->setFileName(fileName);

    _tab->addTab(editor, itemText);
    //设置tab控件为当前打开的文件
    _tab->setCurrentIndex(_tab->count() - 1);
    file.close();
}

void MainWindow::onTabWidgetClosed(int index)
{
    QWidget* widget = _tab->widget(index);
    if (widget != nullptr) {
        Editor* editor = static_cast<Editor*>(widget);
        //notice the order, delete must stay after the removeTab
        _tab->removeTab(index);
        delete editor;
    }
}

void MainWindow::onFileListItemChanged(QStandardItem *item)
{
    Editor* currentEditor = (Editor*)_tab->currentWidget();
    //获取新文件名字
    QString filename = currentEditor->getFileName();
    qsizetype index = filename.lastIndexOf("/");
    QString newFile = filename.mid(0, index + 1) + item->text();
    currentEditor->setFileName(newFile);
    //重命名
    QFile::rename(filename, newFile);
    _tab->setTabText(_tab->currentIndex(), item->text());
}

void MainWindow::getSubdirAndFiles(QString dir, QString prefix, QStandardItem* itemModel)
{
    QDir projectPath(dir);

    QStringList fileList = projectPath.entryList(QDir::Files);
    foreach (const QString& file, fileList) {
        QStandardItem* item = new QStandardItem(file);
        if (itemModel) {
            itemModel->appendRow(item);
        } else {
            _model->appendRow(item);
        }
    }

    QStringList dirList = projectPath.entryList(QDir::Dirs|QDir::NoDot|QDir::NoDotDot);
    foreach (const QString& dir, dirList) {
        QString childPath = prefix + "/" + dir;
        QStandardItem* item = new QStandardItem(childPath);
        if (itemModel) {
            itemModel->appendRow(item);
        } else {
            _model->appendRow(item);
        }
        getSubdirAndFiles(childPath, childPath, item);
    }
}


void MainWindow::on_new_file_triggered()
{
    bool ok = false;
    QString inputName = QInputDialog::getText(this, tr("新建文件"), tr("请输入文件名"), QLineEdit::Normal, tr("utilite.xg"), &ok);
    if (ok) {
        QStandardItem* item = new QStandardItem(inputName);
        item->setEditable(true);

        QString filename = _project + "/" + item->text();
        QFile file(filename);
        if (file.open(QIODevice::WriteOnly)) {
            _model->appendRow(item);
            Editor* editor = new Editor();
            editor->setFileName(filename);

            _tab->addTab(editor, "utilite.xg");
            _tab->setCurrentIndex(_tab->count() - 1);
            file.close();
        }
    }
}


void MainWindow::on_save_code_triggered()
{
    Editor* editor = (Editor*)_tab->currentWidget();
    if (!editor->saveFile()) {
        QMessageBox::warning(this, tr("错误"), tr("文件保存失败"), QMessageBox::Ok);
    }
}


void MainWindow::on_run_code_triggered()
{
    Editor* editor = (Editor*)_tab->currentWidget();
    if (editor == nullptr) {
        return;
    }
    bool isRun = false;
    QString fileName = editor->getFileName();
    for (int i = 0; i < _console->count(); ++i) {
        ConsoleEditor* widget = (ConsoleEditor*)_console->widget(i);
        if (widget->getFileName() == fileName) {
            _console->setCurrentIndex(i);
            isRun = true;
            break;
        }
    }
    if (!isRun) {
        ConsoleEditor* ceditor = new ConsoleEditor(this);
        ceditor->setFileName(fileName);
        qsizetype index = fileName.lastIndexOf("/");
        if (index != -1) {
            _console->addTab(ceditor, fileName.sliced(index + 1));
        }
        _console->setCurrentIndex(_console->count() - 1);
    }

    QProcess* process = new QProcess(this);
    QString pro = "xg";
    QStringList arg;
    arg << fileName;
    connect(process, &QProcess::finished, [this](int exitCode) {
        if (exitCode) {
            QMessageBox::warning(this, "提示", "程序运行失败");
        }
    });
    bool isSetCmd = false;
    connect(process, &QProcess::readyReadStandardOutput, [&]() {
        QString con = QString::fromUtf8(process->readAllStandardOutput());
        if (!isSetCmd) {
            isSetCmd = true;
            con = pro + " " + fileName + "\r\n" + con;
        }
        ConsoleEditor* ceditor = (ConsoleEditor*)_console->currentWidget();
        ceditor->appendPlainText(con);
    });
    process->start(pro, arg);
    bool runOk = process->waitForFinished();
    if (!runOk) {
        QMessageBox::warning(this, "提示", "程序运行失败");
    }
    delete process;
}

